﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
namespace Piao
{
    public interface ILog
    {
        void Debug(string format, params object[] words);
        void Error(string format, params object[] words);
        void Message(string format, params object[] words);
    }

    public class ConsoleLog : ILog
    {
        private readonly ConsoleColor foreColor = Console.ForegroundColor;

        #region ILog Members

        public void Debug(string format, params object[] words)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(format, words);
            Console.ForegroundColor = foreColor;
        }
        public void Error(string format, params object[] words)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(format, words);
            Console.ForegroundColor = foreColor;
        }

        public void Message(string format, params object[] words)
        {
            Console.WriteLine(format, words);
        }

        #endregion
    }

    public class FormLog : ILog
    {
        static int counter = 0;
        private delegate void LogDelegate(string arg);
        private readonly System.Windows.Forms.RichTextBox logcontrol;

        public FormLog(System.Windows.Forms.Control ctrl)
        {
            logcontrol = ctrl as RichTextBox;
        }

        void ILog.Debug(string format, params object[] words)
        {
#if DEBUG

            string line = string.Format(format, words) + Environment.NewLine;
            LogDelegate del = new LogDelegate(s =>
            {
                AppendText(logcontrol, s, System.Drawing.Color.Green);
            });

            var form = logcontrol.FindForm();

            if (form != null && !form.IsDisposed && form.Created)
                logcontrol.Invoke(del, line);
#endif
        }

        public void Error(string format, params object[] words)
        {
            string line = string.Format(format, words) + Environment.NewLine;
            LogDelegate del = new LogDelegate(s =>
            {
                AppendText(logcontrol, s, System.Drawing.Color.Red);
            });

            var form = logcontrol.FindForm();

            if (form != null && !form.IsDisposed && form.Created)
                logcontrol.Invoke(del, line);
        }

        public void Message(string format, params object[] words)
        {
            string line = string.Format(format, words) + Environment.NewLine;
            LogDelegate del = new LogDelegate(s =>
            {
                AppendText(logcontrol, s, System.Drawing.Color.Black);
            });

            var form = logcontrol.FindForm();

            if (form != null && !form.IsDisposed && form.Created)
                logcontrol.Invoke(del, line);
        }


        private static void AppendText(RichTextBox box, string text, System.Drawing.Color color)
        {
            if (counter++ > 200)
            {
                counter = 0;
                box.Text = string.Empty;
            }


            box.SelectionStart = box.TextLength;
            box.SelectionLength = 0;

            box.SelectionColor = color;
            box.AppendText(text);
            box.SelectionColor = box.ForeColor;
            box.ScrollToCaret();
        }


    }


    public static class Log
    {

        static Log()
        {
            ConsoleLog cl = new ConsoleLog();
            Add(cl);
        }

        private static List<ILog> list = new List<ILog>();
        public static void Add(ILog log)
        {
            if (!list.Contains(log))
            {
                list.Add(log);
            }
        }


        private static string MethodName()
        {
#if DEBUG
            StackFrame sf2 = new StackFrame(2);
            return string.Format("[{0}]", sf2.GetMethod().Name);
#else
            return string.Empty;
#endif

        }

        public static void Debug(string format, params object[] words)
        {
            string name = MethodName();
            foreach (var item in list)
            {
                item.Debug(name + format, words);
            }
        }

        public static void Error(string format, params object[] words)
        {
            string name = MethodName();
            foreach (var item in list)
            {
                item.Error(name + format, words);
            }
        }

        public static void Message(string format, params object[] words)
        {
            string name = MethodName();
            foreach (var item in list)
            {
                item.Message(name + format, words);
            }
        }


    }


}
